import os
import time
from ctypes import *

class USBI2C():
    ch341 = windll.LoadLibrary("CH341DLL.dll")
    dev_addr_start = 0x00
    dev_addr_end = 0xff
    def __init__(self, usb_dev = 0, i2c_dev = 0x5c , commfreq = 0x82):
        print('USBI2C init {:#x} {:#x} {:#x}'.format(usb_dev,i2c_dev,commfreq))
        self.usb_id   = usb_dev
        self.usb_init = False #usb
        self.dev_connected = False #iic
        self.iic_interval = 0.8 #iic命令最低间隔时间
        if USBI2C.ch341.CH341OpenDevice(self.usb_id) != -1:
            USBI2C.ch341.CH341SetStream(self.usb_id, commfreq)
            USBI2C.ch341.CH341CloseDevice(self.usb_id)
            print('USB CH341 init Ok!')
            self.usb_init = True
        else:
            print("USB CH341 init Failed!")
            self.usb_init = False
            self.dev_connected = False
    def set_usb_freq(self,commfreq):
        print('set_usb_freq')
        if USBI2C.ch341.CH341OpenDevice(self.usb_id) != -1:
            USBI2C.ch341.CH341SetStream(self.usb_id, commfreq)
            USBI2C.ch341.CH341CloseDevice(self.usb_id)
            print('set_usb_freq Ok!')
    def get_s16(self,val): #c语言有符号数转为python有符号数
        if val < 0x8000:
            return val
        else:
            return (val - 0x10000)

    def convertHtoF(self,s):
        print('1,',s)
        i = int(s, 16)  # convert from hex to a Python int
        cp = pointer(c_int(i))  # make this into a c integer
        fp = cast(cp, POINTER(c_float))  # cast the int pointer to a float pointer
        print('2,',fp.contents.value)
        return fp.contents.value  # dereference the pointer, get the float

    def read(self, addr=None):
        if USBI2C.ch341.CH341OpenDevice(self.usb_id) != -1:
            ibuf = (c_byte * 1)()
            if addr != None:
                obufl = [self.dev_addr, addr]
            else:
                obufl = [self.dev_addr]
            datacnt = len(obufl)
            obuf = (c_byte * datacnt)()
            for x in range(datacnt):
                obuf[x] = obufl[x] & 0xff
            #print('write', [hex(x) for x in obufl], datacnt)
            USBI2C.ch341.CH341StreamI2C(self.usb_id, datacnt, obuf, 1, ibuf)
            USBI2C.ch341.CH341CloseDevice(self.usb_id)
            return ibuf[0] & 0xff
        else:
            print("USB CH341 Open Failed!")
            self.usb_init = False
            self.dev_connected = False
            return 0

    def readb(self, addr = None,cntbyte = 1): #读连续字节，返回格式化的hex列表
        if USBI2C.ch341.CH341OpenDevice(self.usb_id) != -1:
            tmpl = []
            #obuf = (c_byte * 2)()
            ibuf = (c_byte * cntbyte)()
            if addr != None:
                obufl = [self.dev_addr, addr]
            else:
                obufl = [self.dev_addr]
            datacnt = len(obufl)
            obuf = (c_byte * datacnt)()
            for x in range(datacnt):
                obuf[x] = obufl[x] & 0xff
            USBI2C.ch341.CH341StreamI2C(self.usb_id, datacnt, obuf, cntbyte, ibuf)
            USBI2C.ch341.CH341CloseDevice(self.usb_id)
            #print(type(ibuf),len(ibuf))
            for x in range(len(ibuf)):
                #print(ibuf[x]& 0xff)
                tmpl.append(ibuf[x]& 0xff) #数据
            #print([x for x in tmpl])
            if len(ibuf) > 1:
                return tmpl
            else:
                return tmpl[0]
            #return [(ibuf[x]& 0xff) for x in range(cntbyte)]
        else:
            self.usb_init = False
            self.dev_connected = False
            print("USB CH341 Open Failed!")
            return 0

    def write(self, addr = None, dat = 0):
        if USBI2C.ch341.CH341OpenDevice(self.usb_id) != -1:
            #print('write',addr,dat)
            ibuf = (c_byte * 1)()
            obufl = []
            if addr != None:
                obufl = [self.dev_addr, addr]
            else:
                obufl = [self.dev_addr]
            if type(dat) == list:
                obufl += dat
            else:
                obufl.append(dat)
            datacnt = len(obufl)
            obuf = (c_byte * datacnt)()
            for x in range(datacnt):
                obuf[x] = obufl[x] & 0xff
            #print('write',[hex(x) for x in obufl],datacnt)
            USBI2C.ch341.CH341StreamI2C(self.usb_id, datacnt, obuf, 0, ibuf)
            USBI2C.ch341.CH341CloseDevice(self.usb_id)
        else:
            self.usb_init = False
            self.dev_connected = False
            print("USB CH341 Open Failed!")
        pass

    def read_paskaL(self, addr=None, cntbyte=1, datatypelen=1):  # 读连续字节，打印压力值
        if USBI2C.ch341.CH341OpenDevice(self.usb_id) != -1:
            ibuf = (c_byte * cntbyte)()
            if addr != None:
                obufl = [self.dev_addr, addr]
            else:
                obufl = [self.dev_addr]
            datacnt = len(obufl)
            obuf = (c_byte * datacnt)()
            for x in range(datacnt):
                obuf[x] = obufl[x] & 0xff
            USBI2C.ch341.CH341StreamI2C(self.usb_id, datacnt, obuf, cntbyte, ibuf)
            USBI2C.ch341.CH341CloseDevice(self.usb_id)
            # print(type(ibuf),len(ibuf))
            l = []
            tmpl = []
            tmp = 0
            cnttmp = 0
            offset = 1
            for x in range(len(ibuf)):
                if x < offset:
                    l.append(ibuf[x] & 0xff)  # 状态位
                else:
                    tmpl.append(ibuf[x] & 0xff)  # 数据
            # print(tmpl)
            for x in range(len(tmpl)):
                cnttmp += 1
                idx = x % datatypelen
                tmp += (tmpl[x] << idx * 8)
                if cnttmp % datatypelen == 0:
                    tmp = self.get_s16(tmp)
                    l.append(tmp)
                    tmp = 0
            return l
            # return [(ibuf[x]& 0xff) for x in range(cntbyte)]
        else:
            self.usb_init = False
            self.dev_connected = False
            print("USB CH341 Open Failed!")
            return 0

    def readl(self, addr,cntbyte,datatypelen = 2,offset = 1): #读连续字节，打印sgxv2
        if USBI2C.ch341.CH341OpenDevice(self.usb_id) != -1:
            obuf = (c_byte * 2)()
            ibuf = (c_byte * cntbyte)()
            obuf[0] = self.dev_addr
            obuf[1] = addr
            USBI2C.ch341.CH341StreamI2C(self.usb_id, 2, obuf, cntbyte, ibuf)
            USBI2C.ch341.CH341CloseDevice(self.usb_id)
            #print(type(ibuf),len(ibuf))
            l = []
            tmpl = []
            tmp = 0
            cnttmp = 0
            offset = offset
            for x in range(len(ibuf)):
                if x < offset:
                    l.append(ibuf[x]& 0xff) #状态位
                else:
                    tmpl.append(ibuf[x]& 0xff) #数据
            #print(tmpl)
            for x in range(len(tmpl)):
                cnttmp += 1
                idx = x%datatypelen
                tmp += (tmpl[x]<<idx*8)
                if cnttmp%datatypelen == 0:
                    tmp = self.get_s16(tmp)
                    l.append(tmp)
                    tmp = 0
            return l
            #return [(ibuf[x]& 0xff) for x in range(cntbyte)]
        else:
            self.usb_init = False
            self.dev_connected = False
            print("USB CH341 Open Failed!")
            return 0

    def checkdev_addr(self,addr):
        if addr > self.dev_addr_end:
            return False
        r = self.read(addr)
        if r != 0xff:
            return True
        else:
            return False
        pass
    def setdev_addr(self,addr):
        #print('setdev_addr ',addr)
        self.dev_addr = addr